import { CanActivate, ExecutionContext, Injectable, ForbiddenException } from "@nestjs/common";
import { UserService } from "../user/user.service";
import { Reflector } from "@nestjs/core";
import { CaslAbilityService } from "../auth/casl-ability.service";
import { CaslHandlerType, CHECK_POLICIES_KEY, PolicyHandlerCallBack } from "src/decorators/casl.decorator";

@Injectable()
export class CaslGuard implements CanActivate {
  constructor(
    private reflector: Reflector,
    private caslAbilityService: CaslAbilityService,
  ) {}

  // 守卫原理（面向新手）：
  // 1) 从当前路由处理器（方法/类）上读取装饰器写入的“元数据”，包括：
  //    - HANDLER：@CheckPolicies 提供的策略函数数组 (ability => boolean)
  //    - CAN：@Can 提供的能力允许检查函数 (ability.can(...))
  //    - CANNOT：@Connot 提供的能力禁止检查函数 (ability.cannot(...))
  // 2) 通过 CaslAbilityService 构建当前请求用户的 Ability（AnyMongoAbility）。
  // 3) 依次执行读取到的函数进行校验，任一不通过则拒绝访问。
  // 4) 返回布尔值代表是否允许进入路由处理器。
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // 读取所有层级（方法与类）的元数据；优先方法级，再合并类级
    const handlers = this.reflector.getAllAndMerge<PolicyHandlerCallBack[]>(CHECK_POLICIES_KEY.HANDLER, [
      context.getHandler(),
      context.getClass(),
    ]) as CaslHandlerType;
    const canHandlers = this.reflector.getAllAndMerge<any[]>(CHECK_POLICIES_KEY.CAN, [
      context.getHandler(),
      context.getClass(),
    ]) as CaslHandlerType;
    const cannotHandlers = this.reflector.getAllAndMerge<any[]>(CHECK_POLICIES_KEY.CANNOT, [
      context.getHandler(),
      context.getClass(),
    ]) as CaslHandlerType;
    // 若没有声明任何策略或能力检查，通常视为“无需权限限制”，直接允许
    if (!handlers && !canHandlers && !cannotHandlers) {
      return true;
    }

    const req = context.switchToHttp().getRequest();

    if (!req) {
      return false;
    }
    // 根据当前请求上下文构建 Ability（常见做法：基于用户角色/权限/数据范围）
    const ability = await this.caslAbilityService.forRoot(req.user.username);
    // 逐类检查（策略 -> can -> cannot）
    let flag = true;
    if (handlers?.length) {
      if (handlers instanceof Array) {
        flag = flag && handlers.every((handler) => handler(ability));
      } else if (typeof handlers === "function") {
        flag = flag && handlers(ability);
      }
    }
    if (flag && canHandlers?.length) {
      if (canHandlers instanceof Array) {
        flag = flag && canHandlers.every((handler) => handler(ability));
      } else if (typeof canHandlers === "function") {
        flag = flag && canHandlers(ability);
      }
    }
    if (flag && cannotHandlers?.length) {
      // 对禁止检查：如果任何一个返回 true（表示“禁止条件命中”），则应拒绝
      // 这里保持与现有代码一致，仅作注释说明，不改逻辑
      if (cannotHandlers instanceof Array) {
        flag = flag && cannotHandlers.every((handler) => handler(ability));
      } else if (typeof cannotHandlers === "function") {
        flag = flag && cannotHandlers(ability);
      }
    }

    // 返回总结果；如不通过则抛出带中文提示的 403
    if (!flag) {
      throw new ForbiddenException("您没有权限执行该操作，请联系管理员");
    }
    return true;
  }
}
